package com.youlu.campus.service.postage.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.PostageTemplate;
import com.youlu.campus.entity.PostageTemplateDetail;
import com.youlu.campus.entity.VO.req.PostageTemplateQueryVO;
import com.youlu.campus.service.postage.PostageTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@Service
public class PostageTemplateServiceImpl implements PostageTemplateService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public Page<PostageTemplate> list(PostageTemplateQueryVO requst) {
        log.info(":>>> 开始获取邮费模版:{}", JSON.toJSONString(requst));
        if (Objects.isNull(requst)) {
            requst = new PostageTemplateQueryVO();
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").ne(Boolean.TRUE));
        if (Objects.nonNull(requst.getPricingModel())) {
            query.addCriteria(Criteria.where("pricingModel").is(requst.getPricingModel()));
        }
        if (StringUtils.isNotBlank(requst.getName())) {
            Pattern pattern = Pattern.compile("^.*" + requst.getName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").regex(pattern));
        }
        long count = mongoTemplate.count(query, PostageTemplate.class);
        PageRequest pageRequest = PageRequest.of(requst.getPage() - 1, requst.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort=Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<PostageTemplate> datas = mongoTemplate.find(query.with(pageRequest), PostageTemplate.class);
        return PageableExecutionUtils.getPage(datas, pageRequest, () -> count);
    }

    @Override
    public boolean create(PostageTemplate req) {
        if (Objects.isNull(req) || StringUtils.isBlank(req.getName()) || Objects.isNull(req.getDetails())
                || CollectionUtils.isEmpty(req.getDetails())) {
            log.error(":>>> 添加邮费模版参数错误");
            throw new BusinessException("添加邮费模版参数错误");
        }
        Date date = new Date();
        req.setCreatedTime(date);
        req.setId(null);
        req = mongoTemplate.insert(req);
        for (PostageTemplateDetail detail : req.getDetails()) {
            detail.setCreatedTime(date);
            detail.setId(null);
            detail.setPostageTemplateId(req.getId());
            mongoTemplate.insert(detail);
        }
        return true;
    }

    @Override
    public boolean update(PostageTemplate req) {
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId())) {
            log.error(":>>> 修改邮费模版参数错误");
            throw new BusinessException("修改邮费模版参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        Date date = new Date();
        if (StringUtils.isNotBlank(req.getName())) {
            update.set("name", req.getName());
        }
        if (StringUtils.isNotBlank(req.getDesc())) {
            update.set("desc", req.getDesc());
        }
        if (Objects.nonNull(req.getPrice())) {
            update.set("price", req.getPrice());
        }
        if (Objects.nonNull(req.getPricingModel())) {
            update.set("pricingModel", req.getPricingModel());
        }
        if (Objects.nonNull(req.getPriority())) {
            update.set("priority", req.getPriority());
        }
        update.set("expressFeeTips", req.getExpressFeeTips());
        update.set("expressDesc", req.getExpressDesc());
        update.set("updatedTime", date);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, PostageTemplate.class);
        List<String> detailIds = new ArrayList<>();
        for (PostageTemplateDetail detail : req.getDetails()) {
            if (StringUtils.isNotBlank(detail.getId())) {
                Query queryDetail = new Query().addCriteria(Criteria.where("id").is(detail.getId()));
                Update updateDetail = new Update();
                if (StringUtils.isNotBlank(detail.getProvince())) {
                    updateDetail.set("province", detail.getProvince());
                }
                if (Objects.nonNull(detail.getPrice())) {
                    updateDetail.set("price", detail.getPrice());
                }
                updateDetail.set("updatedTime", date);
                mongoTemplate.updateFirst(queryDetail, updateDetail, PostageTemplateDetail.class);
                detailIds.add(detail.getId());
            } else {
                detail.setId(null);
                detail.setPostageTemplateId(req.getId());
                detail.setCreatedTime(new Date());
                detail = mongoTemplate.insert(detail);
                detailIds.add(detail.getId());
            }

        }
        Query queryR = new Query().addCriteria(Criteria.where("id").nin(detailIds).and("postageTemplateId").is(req.getId()));
        mongoTemplate.remove(queryR, PostageTemplateDetail.class);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public boolean delete(String id) {
        Query queryTemplate = new Query().addCriteria(Criteria.where("postageTemplateId").is(id));
        mongoTemplate.remove(queryTemplate, PostageTemplateDetail.class);
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("deleted", true);
        update.set("updatedTime", new Date());
        mongoTemplate.updateFirst(query, update, PostageTemplate.class);
        return false;
    }

    @Override
    public PostageTemplate findOne(String id) {
        log.info(":>>> 开始查找邮费模版:{}", id);
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        PostageTemplate postageTemplate = mongoTemplate.findOne(query, PostageTemplate.class);
        Query queryTemplate = new Query().addCriteria(Criteria.where("postageTemplateId").is(id));
        List<PostageTemplateDetail> datas = mongoTemplate.find(queryTemplate, PostageTemplateDetail.class);
        if (Objects.nonNull(postageTemplate)) {
            postageTemplate.setDetails(datas);
        }
        return postageTemplate;
    }
    /**
     * 获取邮费模版
     *
     * @param postageTemplate
     * @param province
     * @param expreeFee
     * @return
     */
    @Override
    public HashMap<String, Integer> getOrderExpreeFee(PostageTemplate postageTemplate, String province, Integer expreeFee) {
        log.info(":>>> 开始获取省:{},邮费:{},模版:{}", province, expreeFee, JSON.toJSONString(postageTemplate));
        HashMap<String, Integer> res = new HashMap<>();
        if (StringUtils.isBlank(province) || Objects.isNull(postageTemplate)) {
            log.error(":>>> 下单参数错误:省或证书邮费配置为空");
            throw new BusinessException("请联系客服领取!");
        }
        Integer fee = 0;
        Integer extraFee = 0;
        Query query = new Query().addCriteria(Criteria.where("postageTemplateId").is(postageTemplate.getId()).and("province").is(province));
        PostageTemplateDetail p = mongoTemplate.findOne(query, PostageTemplateDetail.class);
        log.info(">>> 偏远地区邮费:{}", JSON.toJSONString(p));
        if (Objects.nonNull(p)) {
            extraFee = p.getPrice().intValue();

        }
        if (Objects.nonNull(expreeFee)) {
            if (expreeFee.compareTo(0) == 1) {
                fee = expreeFee;
            } else {
                fee = postageTemplate.getPrice().intValue();
            }

        } else {
            fee = postageTemplate.getPrice().intValue();
        }
        res.put("fee", fee);
        res.put("extraFee", extraFee);
        return res;
    }
}
